﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XboxUserInterface.Keys;
using System.Runtime.InteropServices;
using System.Collections;

namespace XboxUserInterface.Variables
{
    /// <summary>
    /// Class which contains references to viariables used by multiple classes
    /// </summary>
    public static class Globals
    {
        /// <summary>
        /// The list of schemes currently loaded
        /// </summary>
        private static List<KeyMap> schemes_ = new List<KeyMap>();

        /// <summary>
        /// The currently active scheme
        /// </summary>
        private static Hashtable _currentScheme = new Hashtable();

        /// <summary>
        /// The Currently active scheme
        /// </summary>
        public static KeyMap Active
        {
            get
            {
                foreach (KeyMap m in Schemes)
                {
                    if (m.Active == true)
                        return m;
                }

                return null;
            }

            set
            {
                for (int i = 0; i < Schemes.Count; i++)
                {
                    if (Schemes[i].Active == true)
                        Schemes[i].Active = false;
                    if (Schemes[i].Equals(value))
                        Schemes[i].Active = true;
                }

                setActiveKeys();
            }
        }

        /// <summary>
        /// Updates the ActiveKeys KeyMap with the keys to use from the list of KeyMaps
        /// </summary>
        /// <returns>Active KeyMap</returns>
        public static Hashtable setActiveKeys()
        {
            _currentScheme.Clear();

            foreach (Key k in Active.Keys)
                _currentScheme.Add(k.GamePadKey, k.KeyCode);

            return _currentScheme;
        }

        /// <summary>
        /// The active scheme
        /// </summary>
        public static Hashtable ActiveKeys
        {
            get { return _currentScheme; }
        }

        /// <summary>
        /// The current list of schemes loaded
        /// </summary>
        public static List<KeyMap> Schemes
        {
            get { return schemes_; }
            set { schemes_ = value; }
        }
    }

    /// <summary>
    /// The list of virtual keycodes used in sending keyboard input
    /// </summary>
    public enum KeyboardFunction
    {
        Mouse_Move = 0x1,
        Mouse_XScroll = 0x1000,
        Mouse_YScroll = 0x800,
        Mouse_Scroll = 0x800,
        Mouse_Left = 0x02,
        Mouse_Right = 0x08,
        Cancel = 0x03,
        Mouse_Middle = 0x20,
        Mouse_XButton1 = 0x05,
        Mouse_XButton2 = 0x06,
        Tab = 0x09,
        Clear = 0x0C,
        Enter = 0x0d,
        Shift = 0x10,
        CTRL = 0x11,
        ALT = 0x12,
        Pause = 0x13,
        CAPS = 0x14,
        ESC = 0x1b,
        Space = 0x20,
        Page_Up = 0x21,
        Page_Down = 0x22,
        End = 0x23,
        Home = 0x24,
        Arrow_Left = 0x25,
        Arrow_Up = 0x26,
        Arrow_Right = 0x27,
        Arrow_Down = 0x28,
        Select = 0x29,
        Print = 0x2a,
        Execute = 0x2b,
        Print_Screen = 0x2c,
        Insert = 0x2d,
        Delete = 0x2e,
        Help = 0x2f,
        Keys_0 = 0x30,
        Keys_1 = 0x31,
        Keys_2 = 0x32,
        Keys_3 = 0x33,
        Keys_4 = 0x34,
        Keys_5 = 0x35,
        Keys_6 = 0x36,
        Keys_7 = 0x37,
        Keys_8 = 0x38,
        Keys_9 = 0x39,
        Keys_A = 0x41,
        Keys_B = 0x42,
        Keys_C = 0x43,
        Keys_D = 0x44,
        Keys_E = 0x45,
        Keys_F = 0x46,
        Keys_G = 0x47,
        Keys_H = 0x48,
        Keys_I = 0x49,
        Keys_J = 0x4a,
        Keys_K = 0x4b,
        Keys_L = 0x4c,
        Keys_M = 0x4d,
        Keys_N = 0x4e,
        Keys_O = 0x4f,
        Keys_P = 0x50,
        Keys_Q = 0x51,
        Keys_R = 0x52,
        Keys_S = 0x53,
        Keys_T = 0x54,
        Keys_U = 0x55,
        Keys_V = 0x56,
        Keys_W = 0x57,
        Keys_X = 0x58,
        Keys_Y = 0x59,
        Keys_Z = 0x5a,
        Left_Win = 0x5b,
        Right_Win = 0x5c,
        Sleep = 0x5f,
        Num_0 = 0x60,
        Num_1 = 0x61,
        Num_2 = 0x62,
        Num_3 = 0x63,
        Num_4 = 0x64,
        Num_5 = 0x65,
        Num_6 = 0x66,
        Num_7 = 0x67,
        Num_8 = 0x68,
        Num_9 = 0x69,
        Num_Multiply = 0x6a,
        Num_Add = 0x6b,
        Num_Separator = 0x6c,
        Num_Subtract = 0x6d,
        Num_Decimal = 0x6e,
        Num_Divide = 0x6f,
        F1 = 0x70,
        F2 = 0x71,
        F3 = 0x72,
        F4 = 0x73,
        F5 = 0x74,
        F6 = 0x75,
        F7 = 0x76,
        F8 = 0x77,
        F9 = 0x78,
        F10 = 0x79,
        F11 = 0x7a,
        F12 = 0x7b,
        Num_Lock = 0x90,
        Scroll_Lock = 0x91,
        Left_Shift = 0xa0,
        Right_Shift = 0xa1,
        Left_Control = 0xa2,
        Right_Control = 0xa3,
        Browser_Back = 0xa6,
        Browser_Fwd = 0xa7,
        Browser_Home = 0xac,
        Volume_Mute = 0xad,
        Volume_Down = 0xae,
        Volume_Up = 0xaf,
        Media_Next = 0xb0,
        Media_Prev = 0xb1,
        Media_Stop = 0xb2,
        Media_PlayPause = 0xb3,
        Launch_Mail = 0xb4,

        NoFunctions = 0
    }

    /// <summary>
    /// Key codes that can be associated with analog controller features.
    /// </summary>
    public enum AnalogFunctions
    {
        Mouse_Move = 0xa,
        Mouse_Scroll = 0x8000,
        NoFunctions = 0x0
        /*
        Mouse_XScroll = 0x1000,
        Mouse_YScroll = 0x800
        */
    }

    /// <summary>
    /// Key codes that can be associated with digital controller features.
    /// </summary>
    public enum DigitalFunctions
    {
        Mouse_Left = 0x01,
        Mouse_Right = 0x02,
        Cancel = 0x03,
        Mouse_Middle = 0x20,
        Mouse_XButton1 = 0x05,
        Mouse_XButton2 = 0x06,
        Tab = 0x09,
        Clear = 0x0C,
        Enter = 0x0d,
        Shift = 0x10,
        CTRL = 0x11,
        ALT = 0x12,
        Pause = 0x13,
        CAPS = 0x14,
        ESC = 0x1b,
        Space = 0x20,
        Page_Up = 0x21,
        Page_Down = 0x22,
        End = 0x23,
        Home = 0x24,
        Arrow_Left = 0x25,
        Arrow_Up = 0x26,
        Arrow_Right = 0x27,
        Arrow_Down = 0x28,
        Select = 0x29,
        Print = 0x2a,
        Execute = 0x2b,
        Print_Screen = 0x2c,
        Insert = 0x2d,
        Delete = 0x2e,
        Help = 0x2f,
        Keys_0 = 0x30,
        Keys_1 = 0x31,
        Keys_2 = 0x32,
        Keys_3 = 0x33,
        Keys_4 = 0x34,
        Keys_5 = 0x35,
        Keys_6 = 0x36,
        Keys_7 = 0x37,
        Keys_8 = 0x38,
        Keys_9 = 0x39,
        Keys_A = 0x41,
        Keys_B = 0x42,
        Keys_C = 0x43,
        Keys_D = 0x44,
        Keys_E = 0x45,
        Keys_F = 0x46,
        Keys_G = 0x47,
        Keys_H = 0x48,
        Keys_I = 0x49,
        Keys_J = 0x4a,
        Keys_K = 0x4b,
        Keys_L = 0x4c,
        Keys_M = 0x4d,
        Keys_N = 0x4e,
        Keys_O = 0x4f,
        Keys_P = 0x50,
        Keys_Q = 0x51,
        Keys_R = 0x52,
        Keys_S = 0x53,
        Keys_T = 0x54,
        Keys_U = 0x55,
        Keys_V = 0x56,
        Keys_W = 0x57,
        Keys_X = 0x58,
        Keys_Y = 0x59,
        Keys_Z = 0x5a,
        Left_Win = 0x5b,
        Right_Win = 0x5c,
        Sleep = 0x5f,
        Num_0 = 0x60,
        Num_1 = 0x61,
        Num_2 = 0x62,
        Num_3 = 0x63,
        Num_4 = 0x64,
        Num_5 = 0x65,
        Num_6 = 0x66,
        Num_7 = 0x67,
        Num_8 = 0x68,
        Num_9 = 0x69,
        Num_Multiply = 0x6a,
        Num_Add = 0x6b,
        Num_Separator = 0x6c,
        Num_Subtract = 0x6d,
        Num_Decimal = 0x6e,
        Num_Divide = 0x6f,
        F1 = 0x70,
        F2 = 0x71,
        F3 = 0x72,
        F4 = 0x73,
        F5 = 0x74,
        F6 = 0x75,
        F7 = 0x76,
        F8 = 0x77,
        F9 = 0x78,
        F10 = 0x79,
        F11 = 0x7a,
        F12 = 0x7b,
        Num_Lock = 0x90,
        Scroll_Lock = 0x91,
        Left_Shift = 0xa0,
        Right_Shift = 0xa1,
        Left_Control = 0xa2,
        Right_Control = 0xa3,
        Browser_Back = 0xa6,
        Browser_Fwd = 0xa7,
        Browser_Home = 0xac,
        Volume_Mute = 0xad,
        Volume_Down = 0xae,
        Volume_Up = 0xaf,
        Media_Next = 0xb0,
        Media_Prev = 0xb1,
        Media_Stop = 0xb2,
        Media_PlayPause = 0xb3,
        Launch_Mail = 0xb4,
        NoFunctions = 0x0
    }

    /// <summary>
    /// List of features on the controller
    /// </summary>
    public enum ControllerButtons
    {
        leftTrigger,
        rightTrigger,
        leftButton,
        rightButton,
        xButton,
        yButton,
        aButton,
        bButton,
        backBtn,
        startBtn,
        leftAnalog,
        rightAnalog,
        dUp,
        dLeft,
        dRight,
        dDown,
        nullKey
    }

    /// <summary>
    /// Describes several preset mouse and scroll speeds
    /// </summary>
    public enum MouseSpeeds
    {
        fast = 20,
        med = 15,
        slow = 10,
        verySlow = 1
    }

    /// <summary>
    /// Structure for creating mouse input for use in SendInput
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct MOUSEINPUT
    {
        public int dx;
        public int dy;
        public uint mouseData;
        public uint dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    /// <summary>
    /// Structure for creating keyboard input for use in SendInput
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    /// <summary>
    /// Structure for creating hardware input for use in SendInput
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct HARDWAREINPUT
    {
        public uint uMsg;
        public ushort wParamL;
        public ushort wParamH;
    }

    /// <summary>
    /// Base unit for the SendInput method to add inputs to the keystream
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
        [FieldOffset(0)]
        public int type;

        [FieldOffset(4)]
        public MOUSEINPUT mi;

        [FieldOffset(4)]
        public KEYBDINPUT ki;

        [FieldOffset(4)]
        public HARDWAREINPUT hi;
    }

    /// <summary>
    /// Win32 Constants to use as keycodes and additional data in sending inputs.
    /// </summary>
    public static class Win32Consts
    {
        public const int INPUT_MOUSE = 0;
        public const int INPUT_KEYBOARD = 1;
        public const int INPUT_HARDWARE = 2;
        public const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
        public const uint KEYEVENTF_KEYUP = 0x0002;
        public const uint KEYEVENTF_UNICODE = 0x0004;
        public const uint KEYEVENTF_SCANCODE = 0x0008;
        public const uint XBUTTON1 = 0x0001;
        public const uint XBUTTON2 = 0x0002;
        public const uint MOUSEEVENTF_MOVE = 0x0001;
        public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
        public const uint MOUSEEVENTF_LEFTUP = 0x0004;
        public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
        public const uint MOUSEEVENTF_RIGHTUP = 0x0010;
        public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020;
        public const uint MOUSEEVENTF_MIDDLEUP = 0x0040;
        public const uint MOUSEEVENTF_XDOWN = 0x0080;
        public const uint MOUSEEVENTF_XUP = 0x0100;
        public const uint MOUSEEVENTF_WHEEL = 0x0800;
        public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000;
        public const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
    }
}
